package com.hzb.erp.api.pc.student.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzb.erp.annotation.DataScoped;
import com.hzb.erp.api.mobile.student.pojo.dto.StudentLeaveDTO;
import com.hzb.erp.api.pc.course.entity.Course;
import com.hzb.erp.api.pc.course.mapper.CourseMapper;
import com.hzb.erp.api.pc.lesson.entity.Lesson;
import com.hzb.erp.api.pc.lesson.entity.LessonStudent;
import com.hzb.erp.api.pc.lesson.mapper.LessonMapper;
import com.hzb.erp.api.pc.lesson.service.LessonService;
import com.hzb.erp.api.pc.student.entity.Student;
import com.hzb.erp.api.pc.student.entity.StudentLeave;
import com.hzb.erp.api.pc.student.mapper.StudentMapper;
import com.hzb.erp.api.pc.sys.service.NotificationService;
import com.hzb.erp.common.entity.Staff;
import com.hzb.erp.common.enums.SignStateEnum;
import com.hzb.erp.common.enums.StudentLeaveSateEnum;
import com.hzb.erp.api.pc.student.mapper.StudentLeaveMapper;
import com.hzb.erp.api.pc.student.pojo.StudentLeaveParamDTO;
import com.hzb.erp.api.pc.student.pojo.StudentLeaveVO;
import com.hzb.erp.api.pc.lesson.service.LessonStudentService;
import com.hzb.erp.api.pc.student.service.StudentLeaveService;
import com.hzb.erp.common.mapper.StaffMapper;
import com.hzb.erp.common.service.SettingService;
import com.hzb.erp.exception.BizException;
import com.hzb.erp.sysservice.enums.SettingNameEnum;
import com.hzb.erp.sysservice.notification.NoticeCodeEnum;
import com.hzb.erp.sysservice.notification.bo.StudentLeaveBO;
import com.hzb.erp.utils.CommonUtil;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


/**
 * <p>
 * 学员请假 服务实现类
 * </p>
 *
 * @author Ryan
 */
@Service
public class StudentLeaveServiceImpl extends ServiceImpl<StudentLeaveMapper, StudentLeave> implements StudentLeaveService {

    @Autowired
    private LessonStudentService lessonStudentService;

    @Autowired
    private LessonMapper lessonMapper;
    @Resource
    private CourseMapper courseMapper;
    @Autowired
    @Lazy
    private LessonService lessonService;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private NotificationService notificationService;

    @Autowired
    private SettingService settingService;
    @Autowired
    private StaffMapper staffMapper;

    @Override
    public IPage<StudentLeaveVO> getList(StudentLeaveParamDTO param) {
        IPage<StudentLeaveVO> list = this.baseMapper.getList(new Page<>(param.getPage(), param.getPageSize()), param);
        Boolean marker = settingService.boolValue(SettingNameEnum.STUDENT_MOBILE_MARKER_SWITCH.getCode());
        if(BooleanUtils.isNotFalse(marker) && CollectionUtils.isNotEmpty(list.getRecords())) {
            for (StudentLeaveVO vo: list.getRecords()) {
                vo.setMobile(CommonUtil.markMobile(vo.getMobile()));
            }
        }
        return list;
    }
//
//    @Override
//    public Boolean handle(List<Long> ids, VerifyStateEnum verify) {
//        QueryWrapper<StudentLeave> qw = new QueryWrapper<>();
//        qw.in("id", ids);
//        List<StudentLeave> list = this.list(qw);
//        for (StudentLeave item: list ) {
//            item.setVerifyState(verify);
//        }
//        return this.updateBatchById(list);
//    }//

    @Override
    @Transactional
    public Boolean cancel(List<Long> ids, Long staffId) {
        QueryWrapper<StudentLeave> qw = new QueryWrapper<>();
        qw.in("id", ids);
        List<StudentLeave> list = this.list(qw);
        List<LessonStudent> lsList = new ArrayList<>();

        for (StudentLeave item : list) {
            item.setState(StudentLeaveSateEnum.CANCELED);
            item.setVerifyStaff(staffId);
            item.setVerifyTime(LocalDateTime.now());

            // 取消学员的请假考勤状态
            LessonStudent ls = lessonStudentService.getByLessonIdAndStudentId(item.getLessonId(), item.getStudentId());
            if (ls != null && SignStateEnum.LEAVE.equals(ls.getSignState())) {
                ls.setSignState(SignStateEnum.NONE);
                lsList.add(ls);
            }

        }
        if (lsList.size() > 0) {
            lessonStudentService.updateBatchById(lsList);
        }
        return this.updateBatchById(list);
    }

    @Override
    public boolean handleLeave(StudentLeaveDTO dto) {
        LambdaQueryWrapper<StudentLeave> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(StudentLeave::getStudentId, dto.getStudentId());
        wrapper.eq(StudentLeave::getLessonId, dto.getLessonId());
        wrapper.last("limit 1");
        StudentLeave sl = this.baseMapper.selectOne(wrapper);
        if(sl != null) {
            throw new BizException("请勿重复请假");
        }
        Lesson lesson = lessonMapper.selectById(dto.getLessonId());
        LocalDateTime lessonTime = LocalDateTime.of(lesson.getDate(), lesson.getStartTime());
        if(LocalDateTime.now().isAfter(lessonTime)) {
            throw new BizException("已开始的课不能请假");
        }

        LessonStudent ls = lessonStudentService.getByLessonIdAndStudentId(dto.getLessonId(),dto.getStudentId());
        if (ls != null && SignStateEnum.LEAVE.equals(ls.getSignState())) {
            throw new BizException("上课记录不能重复请假");
        }

        Student student = studentMapper.selectById(dto.getStudentId());
        if(ls == null) {
            // 一般不会有学生没有上课记录的情况，这里以防万一
            ls = new LessonStudent();
            ls.setLessonId(dto.getLessonId());
            ls.setClassId(lesson.getClassId());
            ls.setStudentId(dto.getStudentId());
            ls.setTeacherId(lesson.getTeacherId());
            ls.setConsumeCourseId(lesson.getCourseId());
            ls.setCounselor(student.getCounselor());
            ls.setSignState(SignStateEnum.LEAVE);
            ls.setLessonCount(lesson.getDecCount());
            lessonStudentService.save(ls);
        } else {
            ls.setLessonCount(lesson.getDecCount());
            ls.setSignState(SignStateEnum.LEAVE);
            lessonStudentService.updateById(ls);
        }

        StudentLeave newLeave = new StudentLeave();
        newLeave.setAddTime(LocalDateTime.now());
        newLeave.setStudentId(dto.getStudentId());
        newLeave.setLessonId(dto.getLessonId());
        newLeave.setReason(dto.getReason());
        newLeave.setState(StudentLeaveSateEnum.SUCCESS);
        newLeave.setSchoolId(student.getSchoolId());
        newLeave.setCounselor(student.getCounselor());
        save(newLeave);

        studentLeaveNoticeToTeacher(lesson, student, dto.getReason());
        return true;
    }

    private void studentLeaveNoticeToTeacher(Lesson lesson, Student student, String reason) {
        if (lesson == null || student == null) {
            return;
        }
        StudentLeaveBO bo = new StudentLeaveBO();
        bo.setLessonTitle(lesson.getTitle());
        bo.setDate(lesson.getDate().toString());
        bo.setStartTime(lesson.getStartTime().toString());
        bo.setStudentName(student.getName());
        bo.setSubject(reason);

        List<Staff> teachers = lessonService.getTeachers(lesson);
        Course course = courseMapper.selectById(lesson.getCourseId());

        if (teachers != null && teachers.size() > 0) {
            for (Staff t : teachers) {
                bo.setTeacherName(t.getName());
                bo.setContent(t.getName() + "老师你好，你的课有学生"+student.getName()+"请假");
                notificationService.sendToTeacher(NoticeCodeEnum.TEACHER_STUDENT_LEAVE, bo, t);
            }
        }

        // 额外通知人
        String defaultMobile = settingService.strValue(SettingNameEnum.STUDENT_LEAVE_NOTIFY_MOBILE.getCode());
        if (StringUtils.isNotBlank(defaultMobile)) {
            Staff byMobile = staffMapper.getByMobile(defaultMobile);
            if (byMobile != null) {
                bo.setTeacherName(byMobile.getName());
                bo.setContent(byMobile.getName() + "老师你好，有学生"+student.getName()+"请假");
                notificationService.sendToTeacher(NoticeCodeEnum.TEACHER_STUDENT_LEAVE, bo, byMobile);
            }
        }
    }
}
